package org.concept.chinachesspieces.core;

import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;

/**
 * @author xww 检查棋局是否合法
 */
public class ChessMap {
	public static Logger log = LogManager.getLogger(ChessMap.class);

	public static boolean legal(byte[][] bs) {
		int[] s = RedStep.stepRed(bs);
		return verityNumber(bs) && verityPos(bs) && !Check.checkRed(bs)
				&& s[0] + s[1] > 0;
	}

	public static boolean legalOnBlackFirst(byte[][] bs) {
		int[] s = BlackStep.stepBlack(bs);
		return verityNumber(bs) && verityPos(bs) && !Check.checkBlack(bs)
				&& s[0] + s[1] > 0;
	}

	/**
	 * 判断坐标是否在指定坐标集合
	 * 
	 * @param b
	 *            坐标
	 * @param map
	 *            坐标集合
	 * @return 坐标是否不在指定坐标集合
	 */
	public static boolean notIn(byte b, byte[] map) {
		for (int i = 0; i < map.length; i++) {
			if (map[i] == b) {
				return false;
			}
		}
		return true;
	}

	/**
	 * 判断坐标是否在指定坐标集合
	 * 
	 * @param b
	 *            坐标
	 * @param map
	 *            坐标集合
	 * @return 坐标是否在指定坐标集合
	 */
	public static boolean in(byte b, byte[] map) {
		for (int i = 0; i < map.length; i++) {
			if (map[i] == b) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 判断双方老将是否没有名将
	 * 
	 * @param bs
	 *            棋盘
	 * @return 双方老将是否没有名将
	 */
	public static boolean verityMarshal(byte[][] bs) {
		int redy = 0;
		int blacky = 0;
		int redx = 0;
		int blackx = 0;
		for (int i = 0; i < bs.length; i++) {
			for (int j = 0; j < bs[i].length; j++) {
				if (bs[i][j] == Constants.RED_MARSHAL) {
					redx = i;
					redy = j;
				}
				if (bs[i][j] == Constants.BLACK_MARSHAL) {
					blackx = i;
					blacky = j;
				}
			}
		}
		if (redy == blacky) {
			for (int i = redx + 1; i < blackx; i++) {
				if (bs[i][redy] != Constants.EMPTY) {
					return true;
				}
			}

			return false;
		}
		return true;
	}

	/**
	 * 判断每个棋子的位置是否合法和有没有明将
	 * 
	 * @param bs
	 *            棋盘
	 * @return 每个棋子的位置是否合法和有没有明将
	 */
	public static boolean verityPos(byte[][] bs) {
		for (byte i = 0; i < bs.length; i++) {
			for (byte j = 0; j < bs[i].length; j++) {
				byte pos = (byte) (i * 10 + j);
				byte b = bs[i][j];
				if (b == Constants.RED_SOLDIER) {
					if (pos <= 48
							&& (notIn(pos, Constants.RED_SOLDIER_POS) || bs[(7 - i)][j] == Constants.RED_SOLDIER)) {
						log.info("红兵位置异常");
						return false;
					}
				} else if (b == Constants.RED_ELEPHONT) {
					if (notIn(pos, Constants.RED_ELEPHONT_POS)) {
						log.info("红象位置异常");
						return false;
					}
				} else if (b == Constants.RED_GUESTS) {
					if (notIn(pos, Constants.RED_GUESTS_POS)) {
						log.info("红士位置异常");
						return false;
					}
				} else if (b == Constants.RED_MARSHAL) {
					if (notIn(pos, Constants.RED_MARSHAL_POS)) {
						log.info("红将位置异常");
						return false;
					}
				} else if (b == Constants.BLACK_SOLDIER) {
					if (pos > 48
							&& (notIn(pos, Constants.BLACK_SOLDIER_POS) || bs[(11 - i)][j] == Constants.BLACK_SOLDIER)) {
						log.info("黑兵位置异常");
						return false;
					}
				} else if (b == Constants.BLACK_ELEPHONT) {
					if (notIn(pos, Constants.BLACK_ELEPHONT_POS)) {
						log.info("黑象位置异常");
						return false;
					}
				} else if (b == Constants.BLACK_GUESTS) {
					if (notIn(pos, Constants.BLACK_GUESTS_POS)) {
						log.info("黑士位置异常");
						return false;
					}
				} else if (b == Constants.BLACK_MARSHAL) {
					if (notIn(pos, Constants.BLACK_MARSHAL_POS)) {
						log.info("黑将位置异常");
						return false;
					}
				} else {
					continue;
				}
			}
		}
		if (!verityMarshal(bs)) {
			return false;
		}
		return true;
	}

	/**
	 * 判断棋子数量是否违法
	 * 
	 * @param bs
	 *            棋盘
	 * @return 棋子数量有没有违法
	 */
	public static boolean verityNumber(byte[][] bs) {
		byte[] b = new byte[18];
		for (int i = 0; i < bs.length; i++) {
			for (int j = 0; j < bs[i].length; j++) {
				b[bs[i][j]]++;
			}
		}
		boolean marshal = b[Constants.RED_MARSHAL] == 1
				&& b[Constants.BLACK_MARSHAL] == 1;
		if (!marshal) {
			log.info("老将数量异常");
			return false;
		}
		boolean soldier = b[Constants.RED_SOLDIER] <= 5
				&& b[Constants.BLACK_SOLDIER] <= 5;
		if (!soldier) {
			log.info("士兵数量异常");
			return false;
		}
		for (int i = Constants.RED_CAR; i <= Constants.RED_GUN; i++) {
			if (b[i] > 2) {
				log.info(i + "数量异常");
				return false;
			}
		}
		for (int i = Constants.BLACK_CAR; i <= Constants.BLACK_GUN; i++) {
			if (b[i] > 2) {
				log.info(i + "数量异常");
				return false;
			}
		}
		return true;
	}

}
